从 VTK 过渡到 PyVista简介

VTK 主要在 C++ 中开发,并使用链式 setter 和 getter 命令来访问数据。相反,PyVista 将 VTK 数据类型包装为 numpy 数组,以便用户可以受益于其括号语法和花式索引。本节通过一系列示例演示两种方法之间的差异。

例如,要使用 VTK Python 的绑定为 vtkImageData 数据结构硬编码点,人们会编写以下内容:

code.matlab
import vtk
from math import cos, sin
# 为 300x300 图像数据集创建 (x, y) 点
points = vtk.vtkDoubleArray()
points.SetName("points")
points.SetNumberOfComponents(1)
points.SetNumberOfTuples(300 * 300)
for x in range(300):
    for y in range(300):
        points.SetValue(
            x * 300 + y,
            127.5 + (1.0 + sin(x / 25.0) * cos(y / 25.0)),
        )
# 创建图像结构
image_data = vtk.vtkImageData()
image_data.SetOrigin(0, 0, 0)
image_data.SetSpacing(1, 1, 1)
image_data.SetDimensions(300, 300, 1)
# 将点分配给图像
image_data.GetPointData().SetScalars(points)
如您所见,创建简单的 vtkImageData 数据集需要相当多的样板代码。PyVista 提供了更简洁且更“Pythonic”的语法。PyVista 中的等效代码为:
python
import pyvista as pv
import numpy as np
# 使用 meshgrid 函数创建 x 和 y 值的 2D “网格”。
# 此部分有效地替换了 vtkDoubleArray。
xi = np.arange(300)
x, y = np.meshgrid(xi, xi)
values = 127.5 + (1.0 + np.sin(x / 25.0) * np.cos(y / 25.0))
# 创建网格。注意值必须使用 Fortran 排序。
grid = pv.ImageData(dimensions=(300, 300, 1))
grid.point_data["values"] = values.flatten(order="F")

这里,PyVista 为我们做了几件事:

PyVista 将数据的维度(在 numpy.ndarray 的形状中)与数据的值在一行中组合。VTK 使用“元组”来描述数据的形状(它在空间中的位置)和“组件”来描述数据的类型(1 = 标量/标量场,2 = 向量/向量场,n = 张量/张量场)。这里,形状和值具体存储在一个变量中。

pyvista.ImageData 包装了 vtkImageData,只是名称不同;它们都是均匀间隔点的容器。您的数据不必是“图像”才能将其与 vtkImageData 一起使用;相反,像图像一样,数据集中的值像图像中的像素一样均匀间隔。

此外,由于我们知道容器用于均匀间隔的数据,pyvista 默认将原点和间距设置为 (0, 0, 0) 和 (1, 1, 1)。这是关于 PyVista 和 Python 的另一个很棒的事情。您不必一开始就了解有关 VTK 库的所有内容,您可以非常轻松地开始。一旦您更熟悉它并需要做更复杂的事情,您就可以深入挖掘。例如,更改原点和间距就像以下一样简单:

code.matlab
grid.origin = (10, 20, 10)
grid.spacing = (2, 3, 5)

点数组的名称以字典样式直接给出。此外,由于 VTK 将数据存储在堆上(RAM 的线性段;C++ 概念),数据必须被展平并置于 Fortran 排序中(控制多维数据如何布置在物理 1D 内存中;numpy 默认使用“C”样式内存布局)。这就是为什么在我们之前的示例中,SetValue() 的第一个参数写为 x*300 + y。这里,numpy 非常好地为我们处理了这一点,并且在代码中更加明确,遵循 Python 最佳实践“显式优于隐式”。

最后,使用 PyVista,每个几何类都包含允许您立即绘制网格而无需设置绘图的方法。例如,在 VTK 中您必须执行:

code.matlab
actor = vtk.vtkImageActor()
actor.GetMapper().SetInputData(image_data)
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetWindowName('ReadSTL')
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
ren.AddActor(actor)
iren.Initialize()
renWin.Render()
iren.Start()

但是,使用 PyVista 您只需要:

code.matlab
grid.plot(cpos='xy', show_scalar_bar=False, cmap='coolwarm')
Document Image
\[\]